import { Model } from 'sequelize';
import type { ModelCtor, FindOptions, CreateOptions, UpdateOptions, DestroyOptions } from 'sequelize';
import type { DatabaseConnectionType } from '../connection.js';

/**
 * Repository 基础类，提供通用的数据访问操作
 * @template T 模型实例类型
 * @template TAttributes 模型属性类型
 * @template TCreationAttributes 创建时的属性类型
 */
export abstract class BaseRepository<
  T extends Model<any, any>,
  TAttributes extends Record<string, any>,
  TCreationAttributes extends Record<string, any>
> {
  protected model: ModelCtor<T>;
  protected connection: DatabaseConnectionType;

  constructor(model: ModelCtor<T>, connection: DatabaseConnectionType) {
    this.model = model;
    this.connection = connection;
  }

  /**
   * 创建新记录
   */
  async create(
    data: TCreationAttributes,
    options?: CreateOptions<TAttributes>
  ): Promise<T> {
    try {
      const result = await this.model.create(data as any, options);
      return result;
    } catch (error) {
      this.handleError('create', error);
      throw error;
    }
  }

  /**
   * 根据主键查找记录
   */
  async findByPk(
    id: string | number,
    options?: FindOptions<TAttributes>
  ): Promise<T | null> {
    try {
      return await this.model.findByPk(id, options);
    } catch (error) {
      this.handleError('findByPk', error);
      throw error;
    }
  }

  /**
   * 查找单条记录
   */
  async findOne(options?: FindOptions<TAttributes>): Promise<T | null> {
    try {
      return await this.model.findOne(options);
    } catch (error) {
      this.handleError('findOne', error);
      throw error;
    }
  }

  /**
   * 查找多条记录
   */
  async findAll(options?: FindOptions<TAttributes>): Promise<T[]> {
    try {
      return await this.model.findAll(options);
    } catch (error) {
      this.handleError('findAll', error);
      throw error;
    }
  }

  /**
   * 查找并统计
   */
  async findAndCountAll(options?: FindOptions<TAttributes>): Promise<{
    rows: T[];
    count: number;
  }> {
    try {
      return await this.model.findAndCountAll(options);
    } catch (error) {
      this.handleError('findAndCountAll', error);
      throw error;
    }
  }

  /**
   * 更新记录
   */
  async update(
    values: Partial<TAttributes>,
    options: UpdateOptions<TAttributes>
  ): Promise<[affectedCount: number]> {
    try {
      const [affectedCount] = await this.model.update(values, options);
      return [affectedCount];
    } catch (error) {
      this.handleError('update', error);
      throw error;
    }
  }

  /**
   * 根据主键更新记录
   */
  async updateByPk(
    id: string | number,
    values: Partial<TAttributes>
  ): Promise<T | null> {
    try {
      const [affectedCount] = await this.model.update(values, {
        where: { id } as any,
        returning: true,
      });

      if (affectedCount > 0) {
        return await this.findByPk(id);
      }
      return null;
    } catch (error) {
      this.handleError('updateByPk', error);
      throw error;
    }
  }

  /**
   * 删除记录
   */
  async destroy(options: DestroyOptions<TAttributes>): Promise<number> {
    try {
      return await this.model.destroy(options);
    } catch (error) {
      this.handleError('destroy', error);
      throw error;
    }
  }

  /**
   * 根据主键删除记录
   */
  async destroyByPk(id: string | number): Promise<boolean> {
    try {
      const result = await this.model.destroy({
        where: { id } as any,
      });
      return result > 0;
    } catch (error) {
      this.handleError('destroyByPk', error);
      throw error;
    }
  }

  /**
   * 统计记录数量
   */
  async count(options?: FindOptions<TAttributes>): Promise<number> {
    try {
      return await this.model.count(options);
    } catch (error) {
      this.handleError('count', error);
      throw error;
    }
  }

  /**
   * 批量创建
   */
  async bulkCreate(
    records: TCreationAttributes[],
    options?: CreateOptions<TAttributes>
  ): Promise<T[]> {
    try {
      return await this.model.bulkCreate(records as any[], options);
    } catch (error) {
      this.handleError('bulkCreate', error);
      throw error;
    }
  }

  /**
   * 错误处理
   */
  protected handleError(operation: string, error: any): void {
    const modelName = this.model.name;
    console.error(`❌ Repository Error [${modelName}.${operation}]:`, {
      error: error.message,
      stack: error.stack,
      timestamp: new Date().toISOString(),
    });
  }

  /**
   * 获取数据库连接状态
   */
  async getConnectionStatus(): Promise<boolean> {
    try {
      return await this.connection.isConnected();
    } catch (error) {
      return false;
    }
  }

  /**
   * 开始事务
   */
  async transaction<TResult>(
    callback: (transaction: any) => Promise<TResult>
  ): Promise<TResult> {
    const sequelize = this.connection.getSequelize();
    return await sequelize.transaction(callback);
  }
}